package ua.org.enginer.managers {
	
	import flash.events.EventDispatcher;
	
	import mx.collections.ArrayCollection;
	import mx.managers.CursorManager;
	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.remoting.RemoteObject;
	
	import ua.org.enginer.utils.Cryptor;
	
	[Event(name="result", type="mx.rpc.events.ResultEvent")]
	
	public class CryptedAMFServiceManager extends EventDispatcher {
		
		public var useBusyCursor:Boolean = true
		private var service:RemoteObject
		private var key:String
		/**
		 * Без services-config.xml работатает в режиме очереди... т.е. для логина мне нужно ждать
		 * пока загрузиться всё... не катит )
		 */ 
		function CryptedAMFServiceManager(domain:String, key:String = "enginer",/*source:String = "CryptedService",*/ secure:Boolean=false) {
			super()
			
			this.key = key
			
			service = new RemoteObject(domain+(secure ? "-secure" : ""))
			service.source = "CryptedService"
		}
		
		public function insert(table:String, data:Object, resultHandler:Function=null):void {
			this.resultHandler = resultHandler
			
			service.addEventListener(ResultEvent.RESULT, onInsertResult)
			service.addEventListener(FaultEvent.FAULT, onFault)
			
			if (useBusyCursor) CursorManager.setBusyCursor()
			
			service.insert(Cryptor.encode(table, key), data)
		}
		
		public function update(table:String, data:Object, resultHandler:Function=null):void {
			this.resultHandler = resultHandler
			
			service.addEventListener(ResultEvent.RESULT, onUpdateResult)
			service.addEventListener(FaultEvent.FAULT, onFault)
			
			if (useBusyCursor) CursorManager.setBusyCursor()
			
			service.update(Cryptor.encode(table, key), data)
		}

		private var result:ArrayCollection
		private var resultClass:Class
		private var owner:Object
		public var storageClass:Class
		//private var errorAnswer:String
		
		public function select(table:String, 
								resultClass:Class=null, 
								query:String='', 
								resultHandler:Function=null,
								owner:Object=null):ArrayCollection {
			
			this.resultClass = resultClass
			this.resultHandler = resultHandler
			this.owner = owner
			
			storageClass = storageClass ? storageClass : ArrayCollection
			
			result = new storageClass()
			
			service.addEventListener(ResultEvent.RESULT, onSelectResult)
			service.addEventListener(FaultEvent.FAULT, onFault)
			
			if (useBusyCursor) CursorManager.setBusyCursor()
			
			//trace(table, query)
			//trace(table)
			table = Cryptor.encode(table, key)
			//trace(table)
			query = Cryptor.encode(query, key)
			
			service.select(table, query)
			
			return result
		}
		
		public function login(login:String, password:String, resultHandler:Function):void {
			
			this.resultHandler = resultHandler
			
			//result = new ArrayCollection()
			
			service.addEventListener(ResultEvent.RESULT, onLoginResult)
			service.addEventListener(FaultEvent.FAULT, onFault)
			
			if (useBusyCursor) CursorManager.setBusyCursor()
			
			login = Cryptor.encode(login, key)
			password = Cryptor.encode(password, key)
			
			service.login(login, password)
			
			//return result
		}
		
		public var resultHandler:Function
		
		protected function onSelectResult(event:ResultEvent):void {
			if (useBusyCursor) CursorManager.removeBusyCursor()
			
			event.target.removeEventListener(ResultEvent.RESULT, onSelectResult)
			
			var item:Object
			for each (var o:Object in event.result) {
				if (resultClass) {
					item = new resultClass(o)
					//item.owner = owner ? owner : result
				}else 
					item = o
					
				item.owner = owner ? owner : result
				result.addItem(item)
			}
			
			resultHandler.apply(this, [result])
			resultHandler = null
			
			dispatchEvent(new ResultEvent("result", false, true, result))
		}
		
		protected function onLoginResult(event:ResultEvent):void {
			if (useBusyCursor) CursorManager.removeBusyCursor()
			
			event.target.removeEventListener(ResultEvent.RESULT, onSelectResult)
			
			resultHandler.apply(this, [event.result])
			resultHandler = null
		}
		
		protected function onUpdateResult(event:ResultEvent):void {
			if (useBusyCursor) CursorManager.removeBusyCursor()
			
			event.target.removeEventListener(ResultEvent.RESULT, onUpdateResult)
			
			//errorAnswer = String(event.result)
			
			if (resultHandler) {
				resultHandler.apply(this, [])
				resultHandler = null
			}
		}
		
		protected function onInsertResult(event:ResultEvent):void {
			if (useBusyCursor) CursorManager.removeBusyCursor()
			
			event.target.removeEventListener(ResultEvent.RESULT, onInsertResult)
			
			if (resultHandler) {
				resultHandler.apply(this, [event.result])
				resultHandler = null
			}
		}
		
		
		protected function onFault(event:FaultEvent):void {
			event.target.removeEventListener(FaultEvent.FAULT, onFault)
			if (useBusyCursor) CursorManager.removeBusyCursor()
			trace(event.fault.faultDetail)
		}
	}
}